package com.binarysoft.cmdhandler.type;

import java.util.Collection;
import java.util.StringTokenizer;

import com.binarysoft.service.type.Type;
import com.binarysoft.service.type.TypeService;

import common.framework.command.handler.AbstractCommandHandler;
import common.framework.command.helper.CommandHelper;
import common.framework.command.server.Terminal;
import common.framework.dsb.annotation.DSBCmd;
import common.framework.dsb.client.DefaultServiceFactory;
import common.framework.dsb.client.ServiceFactory;

@DSBCmd("type")
public class TypeCmdHandler extends AbstractCommandHandler {

	@Override
	public void handle(String args, Terminal terminal) throws Exception {
		terminal.println("");
		StringTokenizer stier = new StringTokenizer(args);
		int count = stier.countTokens();
		if (count < 2) {
			terminal.println(" type ls                --list all types");
			terminal.println(" type add               --add new type");
			terminal.println(" type del    <Type ID>  --delete type");
			terminal.println(" type update <Type ID>  --update type");
			terminal.println("");
			return;
		}
		stier.nextToken();
		String cmd = stier.nextToken();
		if ("ls".equalsIgnoreCase(cmd)) {
			listType(terminal, TypeService.ROOT_TYPE_ID);
		} else if ("add".equalsIgnoreCase(cmd)) {
			addType(terminal);
		} else if ("del".equalsIgnoreCase(cmd) && count == 3) {
			String typeID = stier.nextToken();
			deleteType(terminal, typeID);
		} else if ("update".equalsIgnoreCase(cmd) && count == 3) {
			String typeID = stier.nextToken();
			updateType(terminal, typeID);
		} else {
			terminal.println(" type ls                --list all types");
			terminal.println(" type add               --add new type");
			terminal.println(" type del    <Type ID>  --delete type recursively");
			terminal.println(" type update <Type ID>  --update type");
			terminal.println("");
		}
		terminal.println("");
	}

	private void listType(Terminal terminal, String typeID) throws Exception {
		ServiceFactory serviceFactory = new DefaultServiceFactory();
		TypeService typeService = (TypeService) serviceFactory.lookup("DSB/TypeService");
		Type type = typeService.getType(typeID);
		String[] tableHAD = { "Type ID", "Type name" };
		String[] tableGAP = { "-------", "---------" };
		int[] format = { 15, 20 };
		terminal.println(CommandHelper.format(tableHAD, format));
		terminal.println(CommandHelper.format(tableGAP, format));
		printTree(type, terminal, "", typeService);
	}

	private void addType(Terminal terminal) throws Exception {
		listType(terminal, TypeService.ROOT_TYPE_ID);
		terminal.print("Please input the parent type ID:");
		String parentTypeID = terminal.read();
		ServiceFactory serviceFactory = new DefaultServiceFactory();
		TypeService typeService = (TypeService) serviceFactory.lookup("DSB/TypeService");
		if (!typeService.exists(parentTypeID)) {
			terminal.println("Type ID [" + parentTypeID + "] not found.");
			return;
		}
		terminal.print("Please input the new type ID:");
		String newTypeID = terminal.read();
		if (typeService.exists(newTypeID)) {
			terminal.println("Type ID [" + parentTypeID + "] already existed.");
			return;
		}
		terminal.print("Please input the new type Name:");
		String newTypeName = terminal.read();
		terminal.print("Please input the new type Description:");
		String newTypeDescr = terminal.read();
		typeService.addType(newTypeID, newTypeName, newTypeDescr, parentTypeID);
		terminal.println("New type with ID[" + newTypeID + "] and name [" + newTypeName + "] has been created successfully!");
	}

	private void updateType(Terminal terminal, String typeID) throws Exception {
		ServiceFactory serviceFactory = new DefaultServiceFactory();
		TypeService typeService = (TypeService) serviceFactory.lookup("DSB/TypeService");
		Type type = typeService.getType(typeID);
		if (type == null) {
			terminal.println("Type ID [" + typeID + "] not found.");
			return;
		}
		String parentTypeID = type.getParentID();
		terminal.print("Please input new type name:");
		String typeName = terminal.read();
		terminal.print("Please input new type description:");
		String typeDescr = terminal.read();
		terminal.print("Leave the parent type ID unchanged? (yes/no):");
		String opt = terminal.read();
		if ("no".equalsIgnoreCase(opt)) {
			terminal.print("Please input the parent type:");
			parentTypeID = terminal.read();
			if (!typeService.exists(parentTypeID)) {
				terminal.println("Type ID [" + parentTypeID + "] not found.");
				return;
			}
		}
		typeService.updateType(typeID, typeName, typeDescr, parentTypeID);
		terminal.println("Type with ID[" + typeID + "] and new name[" + typeName + "] and new description[" + typeDescr + "] has been changed successfully!");
	}

	private void deleteType(Terminal terminal, String typeID) throws Exception {
		ServiceFactory serviceFactory = new DefaultServiceFactory();
		TypeService typeService = (TypeService) serviceFactory.lookup("DSB/TypeService");
		Type type = typeService.getType(typeID);
		if (type == null) {
			terminal.println("Type ID [" + typeID + "] not found.");
			return;
		}
		terminal.print("Are you sure to delete type[ " + typeID + "] and all it's sub-types recursively ? (yes/no):");
		String opt = terminal.read();
		if ("no".equalsIgnoreCase(opt)) {
			return;
		}
		listType(terminal, typeID);
		terminal.println("");
		Collection<Type> allSubTypes = typeService.getAllSubTypes(typeID);
		allSubTypes.add(type);
		String[] tableHAD = { "Type ID", "Type name", "Type Description", "Parent Type ID" };
		String[] tableGAP = { "-------", "---------", "----------------", "--------------" };
		int[] format = { 15, 20, 25, 15 };
		terminal.println(CommandHelper.format(tableHAD, format));
		terminal.println(CommandHelper.format(tableGAP, format));
		for (Type t : allSubTypes) {
			Object[] row = { t.getID(), t.getName(), t.getDescription(), t.getParentID() };
			terminal.println(CommandHelper.format(row, format));
		}
		terminal.print("Confirm to delete all above " + allSubTypes.size() + " type(s) ? (yes/no):");
		String confirm = terminal.read();
		if ("yes".equalsIgnoreCase(confirm)) {
			typeService.deleteType(typeID);
		}
		terminal.println("Type with ID[" + typeID + "] and name[" + type.getName() + "] has been deleted recursively!");
	}

	private void printTree(Type t, Terminal terminal, String indentation, TypeService typeService) throws Exception {
		terminal.println(indentation + t.getID() + "[" + t.getName() + "]");
		Collection<Type> subTypes = typeService.getSubTypes(t.getID());
		for (Type subType : subTypes) {
			printTree(subType, terminal, indentation + "|   ", typeService);
		}
	}
}
